package com.tianji.learning.service.impl;

import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.utils.LearningRecordDelayTaskHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2025-03-08
 */
@Service
@RequiredArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    private final ILearningLessonService lessonService;
    private final CourseClient courseClient;
    private final LearningRecordDelayTaskHandler delayTaskHandler;

    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询课表信息
        LearningLesson lesson = lessonService.queryByUserIdAndCourseId(userId, courseId);
        if (lesson == null) {
            return null;
        }
        //3.查询学习记录
        //selct * from xx where lesson_id = ? and user_id = ?
        List<LearningRecord> records = lambdaQuery()
                .eq(LearningRecord::getLessonId, lesson.getId())
                .list();
        //4.封装结果
        LearningLessonDTO dto = new LearningLessonDTO();
        dto.setId(lesson.getId());
        dto.setLatestSectionId(lesson.getLatestSectionId());
        dto.setRecords(BeanUtils.copyList(records, LearningRecordDTO.class));
        return dto;
    }

    @Override
    @Transactional
    public void addLearningRecord(LearningRecordFormDTO recordFormDTO) {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.处理学习记录
        boolean finished = false;
        if (recordFormDTO.getSectionType() == SectionType.VIDEO) {
            //2.1处理视频
            finished = handleVideoRecord(userId, recordFormDTO);
        } else {
            //2.2.处理考试
            finished = handleExamRecord(userId, recordFormDTO);
        }
        if (!finished) {
            return;
        }
        //3.处理课表记录
        handleLessoningLessonsChanges(recordFormDTO);
    }

    private void handleLessoningLessonsChanges(LearningRecordFormDTO recordFormDTO) {
        //1.查询课表信息
        LearningLesson lesson = lessonService.getById(recordFormDTO.getLessonId());
        if (lesson == null) {
            throw new BizIllegalException("课表信息不存在,无法更新数据！");
        }
        //2.判断是否有新的完成小结
        boolean alllearned = false;

        //3.如果有，则需要查询课程信息
        CourseFullInfoDTO cinfo = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (cinfo == null) {
            throw new BizIllegalException("课程信息不存在,无法更新数据！");
        }
        //4.比较课程是否全部学完：医学玩小结 》= 总小结
        alllearned = lesson.getLearnedSections() + 1 >= cinfo.getSectionNum();

        //5.更新课表
        lessonService.lambdaUpdate()
                .set(lesson.getLearnedSections() == 0, LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .set(alllearned, LearningLesson::getStatus, LessonStatus.FINISHED.getValue())
                .setSql("learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId, lesson.getId())
                .update();
    }

    private boolean handleVideoRecord(Long userId, LearningRecordFormDTO recordFormDTO) {
        //1.查询旧的学习记录
        LearningRecord old = queryOldRecord(recordFormDTO.getLessonId(), recordFormDTO.getSectionId());
//        LearningRecord old = lambdaQuery()
//                .eq(LearningRecord::getUserId, userId)
//                .eq(LearningRecord::getSectionId, recordFormDTO.getSectionId())
//                .one();
        //2.判断是否存在
        if (old == null) {
            //3.不存在，新增
            //3.1转换PO
            LearningRecord learningRecord = BeanUtils.copyBean(recordFormDTO, LearningRecord.class);
            //3.2填充数据
            learningRecord.setUserId(userId);
            //3.3写入数据库
            boolean success = save(learningRecord);
            if (!success) {
                throw new DbException("新增学习记录失败！");
            }
            return false;
        }

        //4.存在，则更新
        //4.1判断是否第一次完成
        boolean finished = !old.getFinished() && recordFormDTO.getMoment() * 2 > recordFormDTO.getDuration();
        if (!finished) {
            LearningRecord record = new LearningRecord();
            record.setLessonId(recordFormDTO.getLessonId());
            record.setSectionId(recordFormDTO.getSectionId());
            record.setMoment(recordFormDTO.getMoment());
            record.setId(old.getId());
            record.setFinished(old.getFinished());
            delayTaskHandler.addLearningRecordTask(record);
            return false;
        }
        //4.2.更新学习记录
        boolean success = lambdaUpdate()
                .set(LearningRecord::getMoment, recordFormDTO.getMoment())
                .set(LearningRecord::getFinished, true)
                .set(LearningRecord::getFinishTime, recordFormDTO.getCommitTime())
                .eq(LearningRecord::getId, old.getId())
                .update();
        if (!success) {
            throw new DbException("更新学习记录失败！");
        }
        //4.3清理缓存
        delayTaskHandler.clearRecordCache(recordFormDTO.getLessonId(), recordFormDTO.getSectionId());
        return finished;
    }

    private LearningRecord queryOldRecord(Long lessonId, Long sectionId) {
        //1.查询缓存
        LearningRecord record = delayTaskHandler.readRecordCache(lessonId, sectionId);
        //2.如果命中，则直接返回
        if (record != null) {
            return record;
        }
        //3.如果未命中，则查询数据库
        record = lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId)
                .eq(LearningRecord::getSectionId, sectionId)
                .one();
        //4.写入缓存
        delayTaskHandler.writeRecordCache(record);
        return record;
    }

    private boolean handleExamRecord(Long userId, LearningRecordFormDTO recordFormDTO) {
        //1.转换DTO为PO
        LearningRecord learningRecord = BeanUtils.copyBean(recordFormDTO, LearningRecord.class);
        //2.填充数据
        learningRecord.setUserId(userId);
        learningRecord.setFinished(true);
        learningRecord.setFinishTime(recordFormDTO.getCommitTime());
        //3.写入数据库
        boolean success = save(learningRecord);
        if (!success) {
            throw new DbException("新增考试记录失败！");
        }
        return true;
    }

}
